
extern void printf(char * string , ... );

/* Interrupt Descriptor */
typedef struct{
	unsigned short offset_1;
	unsigned short selector;
	unsigned char zero;
	union
	{
		struct{
			unsigned char gatetype : 4;
			unsigned char s : 1;
			unsigned char dpl : 2;
			unsigned char p : 1;
		};
		unsigned char type;
	} ;
	unsigned short offset_2;
} IDTDesc;

typedef struct {
	unsigned char zero	: 2;
	unsigned short limit	: 14;
	unsigned int base	: 32;
} IDTR;



/* Interrupt Descriptor Table for only 32 Interrupts */
IDTDesc IDT[32];

/* Interrupt Descriptor Table Register */
IDTR idtr;


#define iret() __asm__ ("iret"::)

#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \
	"movw %0,%%dx\n\t" \
	"movl %%eax,%1\n\t" \
	"movl %%edx,%2" \
	: \
	: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
	"o" (*((char *) (gate_addr))), \
	"o" (*(4+(char *) (gate_addr))), \
	"d" ((char *) (addr)),"a" (0x00080000))

#define set_intr_gate(n,addr) \
	_set_gate(&idt[n],14,0,addr)

#define set_trap_gate(n,addr) \
	_set_gate(&idt[n],15,0,addr)

#define set_system_gate(n,addr) \
	_set_gate(&idt[n],15,3,addr)

#define	merge( a , b ) a ## b

int idt[32];


/* Divide Error */
void int0(void)
{
	printf("int0\n");
}

/* Debug Exceptions */
void int1(void)
{
	printf("int1\n");
}

/* Breakpoint */
void int3(void)
{
	printf("int3\n");
}

/* Overflow */
void int4(void)
{
	printf("int4\n");
}

/* Bounds Check */
void int5(void)
{
	printf("int5\n");
}

/* Invalid Opcode */
void int6(void)
{
	printf("int6\n");
}

/* Coprocessor Not Available */
void int7(void)
{
	printf("int7\n");
}

/* Double Fault */
void int8(void)
{
	printf("int8\n");
}

/* Coprocessor Segment Overrun */
void int9(void)
{
	printf("int9\n");
}

/* Invalid TSS */
void int10(void)
{
	printf("int10\n");
}

/* Segment Not Present */
void int11(void)
{
	printf("int11\n");
}

/* Stack Exception */
void int12(void)
{
	printf("int12\n");
}

/* General Protection Exception (Triple Fault) */
void int13(void)
{
	printf("int13\n");
}

/* Page Fault */
void int14(void)
{
	printf("int14\n");
}


/* Coprocessor Error */
void int16(void)
{
	printf("int16\n");
}

void reservedInt(void)
{
	printf("Reserved\n");
}


void int_init()
{

	/* Local Variables*/
	int i;
	

	/* Setup Interrupts */
	set_trap_gate(0,&int0);
	set_trap_gate(1,&int1);
	set_trap_gate(2,&reservedInt);
	set_trap_gate(3,&int3);
	set_trap_gate(4,&int4);
	set_trap_gate(5,&int5);
	set_trap_gate(6,&int6);
	set_trap_gate(7,&int7);
	set_trap_gate(8,&int8);
	set_trap_gate(9,&int9);
	set_trap_gate(10,&int10);
	set_trap_gate(11,&int11);
	set_trap_gate(12,&int12);
	set_trap_gate(13,&int13);
	set_trap_gate(14,&int14);
	set_trap_gate(15,&reservedInt);
	set_trap_gate(16,&int16);

	for( i = 17 ; i < 32 ;i++ )
	{
		set_trap_gate(i,&reservedInt);
	}
	set_trap_gate(0,&int0);
	set_trap_gate(0,&int0);

	/* IDTR*/
	idtr.limit = sizeof( IDTR ) * 32 - 1;
	idtr.base  = &IDT;

	IDTR* p = &idtr;

	__asm__("LIDT (%0) ": :"p" (p));
}
